#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <fstream>
#include <iostream>
#include <QMessageBox>
#include <nouvellenotedialog.h>
#include <acceuil.h>
#include <QIcon>
#include <QFileDialog>
#include <QPrinter>
#include <QPainter>
#include <stdio.h>
#include <sstream>
#include <QTimer>
#include <SleeperThread.h>
#include <stdlib.h>
using namespace std;
using std::fstream;

void MainWindow::auto_save(){
    this->setCursor(Qt::BusyCursor);
    FILE * file = fopen(this->filename.toStdString().c_str(),"w");
    fprintf(file, ui->textEdit->toPlainText().toStdString().c_str());
    fprintf(file, "\n");
    fclose(file);


    // save file metadata
    QTextCursor myCursor = ui->textEdit->textCursor();
    // Ordering image hyperlink after its position
    QMap<int, QString> orderedImageList;
    QHash<QString, int>::iterator i;
    for (i = imagePositionList.begin(); i != imagePositionList.end(); ++i)
        orderedImageList.insert(i.value(),i.key());

    // create line to persist
    QString picPosition;
    QMap<int, QString>::iterator j;
    for (j = orderedImageList.begin(); j != orderedImageList.end(); j++)
        picPosition = picPosition + QString::number(j.key()) + "*" + j.value() + "\n";
    ui->textEdit->setTextCursor(myCursor);

    // persist image
    string metadataFullName = file_util::split(this->filename.toStdString(),'/').back();
    string metadataName = file_util::split(metadataFullName,'.').at(0);
    metadataName = ".data/img_" + metadataFullName;
    file = fopen(metadataName.c_str(),"w");
    fprintf(file, picPosition.toStdString().c_str());
    fclose(file);

    // save abbreviation
    QString abbr ;
    QHash<QString, QString>::iterator k;
    // separator is space
    for (k = abbreviationList.begin(); k != abbreviationList.end(); k++)
        abbr = abbr + k.key() + " " + k.value() + "\n";

    // pesist abbreviation
    metadataName = file_util::split(metadataFullName,'.').at(0);
    metadataName = ".data/abb_" + metadataFullName;
    file = fopen(metadataName.c_str(),"w");
    fprintf(file, abbr.toStdString().c_str());
    fclose(file);


    this->setCursor(Qt::ArrowCursor);
    statusBar()->showMessage(QString::fromUtf8("Fichier sauvergardé!"),2000);
}

MainWindow::MainWindow(QString str, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    isNormal = true;
    isTextEditorLoading = true;
    this->count_code = 1;
    ui->setupUi(this);
    createActions();
    createToolbars();
    connect(ui->textEdit,SIGNAL(textChanged()),this,SLOT(textEditorChanged()));
    /* auto save timer */
    QTimer *timer = new QTimer(this);
    timer->setInterval(10000);
    connect(timer, SIGNAL(timeout()), this, SLOT(auto_save()));
    timer->start();

    if(str != "")
    {

        // Load text
        QString content = ".notes/" + str;
        std::ifstream ifs(content.toStdString().c_str());
        std::string str2(
                    (std::istreambuf_iterator<char>(ifs)),
                    std::istreambuf_iterator<char>()
                    );
        ui->textEdit->setText(tr(str2.c_str()));
        // update textSize
        noteSize = str2.size();
        // Load image
//        QString image = ".data_" + str;
        QString image = "img_" + str;
        QString abbreviation = "abb_" + str;


        // check if file has images
        bool hasImage = false;
        vector<string> fileList = file_util::listDirectory(".data");
        for (int i = 0; i < fileList.size(); i++)
            if (image.toStdString().compare(fileList[i]) == 0)
            {
                hasImage = true;
                break;
            }
        // yes
        if (hasImage)
        {
            image = ".data/" + image;
            std::ifstream inputImg(image.toStdString().c_str());
            for( std::string line; getline( inputImg, line ); )
            {
                string link = file_util::split(line,'*').at(1);
                string pos = file_util::split(line,'*').at(0);
                QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(QString::fromStdString(link));
                QTextCursor myCursor = ui->textEdit->textCursor();

                // Go to the image position and delete place holder char
                myCursor.setPosition(atoi(pos.c_str()));
                myCursor.deleteChar();

                // Return to the position and insert image
                myCursor.setPosition(atoi(pos.c_str()));
                myCursor.insertFragment(fragment);

                // return the image list to previous state
                imagePositionList.insert(tr(link.c_str()),atoi(pos.c_str()));
                ui->textEdit->setTextCursor(myCursor);
            }
        }

        // check if file has abbreviation
        bool hasAbbreviation = false;
        for (int i = 0; i < fileList.size(); i++)
            if (abbreviation.toStdString().compare(fileList[i]) == 0)
            {
                hasAbbreviation = true;
                break;
            }
        if (hasAbbreviation)
        {
            abbreviation = ".data/" + abbreviation;
            std::ifstream inputAbb(abbreviation.toStdString().c_str());
            for( std::string line; getline( inputAbb, line ); )
            {
                QString abb = QString::fromStdString(file_util::split(line,' ').at(0));
                QString full = QString::fromStdString(file_util::split(line,' ').at(1));

                abbreviationList.insert(abb,full);
            }
        }
        str = ".notes/" + str;
    }

    this->filename = str;
    std::string temp = str.toStdString();
    std::vector<std::string> spli_str = file_util::split(temp,'/');

    std::string temp2 = spli_str[1];
    if(spli_str[1].find('.') != -1){
        temp2 = (spli_str[1]).substr(0,spli_str[1].find("."));
    }

    std::cout << temp2 << std::endl;
    this->name_only = tr(temp2.c_str());

    this->setWindowTitle(this->name_only);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::textEditorChanged()
{
    // The first time, dont update any thing, just let it be...
    if (isTextEditorLoading)
    {
        isTextEditorLoading = false;
        return;
    }

    // update note size
    int newNoteSize = ui->textEdit->toPlainText().size();
    int offset = newNoteSize - noteSize;
    noteSize = newNoteSize;
    int pos = ui->textEdit->textCursor().position();

    // Get last pressed key
    QTextCursor tc = ui->textEdit->textCursor();
    tc.select(QTextCursor::WordUnderCursor);
    QString selectedText = tc.selectedText();
    QChar lastPressedKey;
    if (selectedText.compare("") == 0)
        lastPressedKey = ' ';
    else
        lastPressedKey = selectedText.at(selectedText.size() - 1);

    // If it's a space
    if (offset == 1 && lastPressedKey == ' ')
    {
        // find abbreviation
        tc.movePosition(QTextCursor::Left);
        tc.movePosition(QTextCursor::StartOfWord);
        ui->textEdit->setTextCursor(tc);
        tc = ui->textEdit->textCursor();
        tc.select(QTextCursor::WordUnderCursor);
        selectedText = tc.selectedText();

        // if abbreviation list contains abbreviation
        if (abbreviationList.contains(selectedText))
        {
            QString fullText = abbreviationList.value(selectedText,"");
//            fullText += " ";
            tc.removeSelectedText();
            tc.insertText(fullText);
            // icluding last pressed key
            tc.setPosition(tc.position() + 1);
            ui->textEdit->setTextCursor(tc);
        }
        else
        {
            tc.setPosition(pos);
            ui->textEdit->setTextCursor(tc);
        }
    }

    QHash<QString, int>::iterator i;
    QString key = "";
    if( offset < 0) // delete Text
    {
        int beforeDelete = pos - offset; // pos + abs(obset)
        for (i = imagePositionList.begin(); i != imagePositionList.end(); ++i)
            // image is between delete ran
            if (i.value() >= pos && i.value() < beforeDelete)
            {
                key = i.key();
                break;
            }
        if (key.compare("") != 0)
            imagePositionList.remove(key);
    }

    QHash<QString, int>::iterator j;
    // update position, if a char is deleted, then all the image following its must be updated its index
    // the folowing images must add 1
    for (j = imagePositionList.begin(); j != imagePositionList.end(); ++j)
        if (j.value() > pos)
            j.value() = j.value() + offset;
}

void MainWindow::addAbbr(){
    QMessageBox msg;

    QString newAbbreviation = ui->newAbbreviation->text();
    if (abbreviationList.contains(newAbbreviation))
    {
        statusBar()->showMessage(QString::fromUtf8("Désolé, mais cette abbréviation existe déjà..."),2000);
    }
    else
    {
        QString fullText = ui->valueAbbreviation->text();
        abbreviationList.insert(newAbbreviation,fullText);
        statusBar()->showMessage(QString::fromUtf8("Abbréviation ajoutée..."),2000);
    }

}

void MainWindow::createNewNote(){
    this->close();
    NouvelleNoteDialog *dialog = new NouvelleNoteDialog();
    dialog->show();
}

void MainWindow::openNote(){
    Acceuil *accueil = new Acceuil();
    accueil->show();
}

void MainWindow::exportPdf(){
    QPrinter printer;
    printer.setOutputFormat(QPrinter::PdfFormat);
    QMessageBox msg;

    printer.setOutputFileName(".pdf/" + this->name_only + ".pdf");
    QPainter painter;
    if (! painter.begin(&printer)) { // failed to open file
        msg.setText(QString::fromUtf8("failed to open file, is it writable?"));
        msg.exec();
    }
    painter.drawText(10, 10, ui->textEdit->toPlainText());
    if (! printer.newPage()) {
        msg.setText(QString::fromUtf8("failed in flushing page to disk, disk full?"));
        return;
    }
    painter.drawText(10, 10, "Test 2");
    painter.end();

    QString tmp = "Fichier enregistré sous " + this->name_only + ".pdf";
    msg.setText(QString::fromUtf8(tmp.toStdString().c_str()));
    msg.exec();


}

void MainWindow::on_buttonModeNormal_clicked()
{
    QPixmap pixmap_normal(":img/mode_normal.png");
    QIcon normalIcon(pixmap_normal);

    QPixmap pixmap_code(":img/mode_code.png");
    QIcon codeIcon(pixmap_code);
    QString code;

    if(isNormal){
        isNormal = false;
        ui->buttonModeNormal->setIcon(normalIcon);
        marker_start = ui->textEdit->textCursor().position();
        ui->textEdit->setStyleSheet("background-color:#ddd");
    }else{

        ui->textEdit->setStyleSheet("background-color:#fff");
        marker_end = ui->textEdit->textCursor().position();
        code = ui->textEdit->toPlainText().mid(marker_start,marker_end);
        if(code != ""){
            //max length = 40
            QString format_code = "\n_______________________________________";
            format_code += "_______________________________________________\n";

            int sub_count = 0;
            int nb_ligne = 0;
            for(int i = 0; i < code.length(); i++){
                sub_count++;
                if(code.at(i) == '\n' || i == 0){
                    if(i == 0){
                        format_code += "|";
                    }
                    nb_ligne++;
                    if(sub_count < 40){
                        int temp = 0;
                        if(nb_ligne < 10){
                            temp = 42;
                        }else{
                            temp = 40;
                        }
                        for(int j = 0; j < temp - sub_count; j++){
                            format_code += " ";
                        }
                    }
                    //format_code += "|";
                    format_code += "\n";
                    format_code += "| ";
                    format_code += QString::number(nb_ligne);
                    format_code += "     ";
                    sub_count = 2 + QString::number(nb_ligne).length();
                    continue;
                }

                format_code += code.at(i);
                if(i == code.length() - 1){
                    if(sub_count < 40){
                        for(int j = 0; j < 40 - sub_count; j++){
                            format_code += " ";
                        }
                    }
                    format_code += "\n";
                }
            }
            format_code += "|______________________________________";

            format_code+= "________________________________________\n";

            QString full_text = (ui->textEdit->toPlainText().mid(0,marker_start));
            full_text += format_code;
            full_text += ui->textEdit->toPlainText().mid(marker_end);
            ui->textEdit->setText(full_text);
        }
        isNormal = true;
        ui->buttonModeNormal->setIcon(codeIcon);
    }



    /*std::stringstream out;
    out << (this->count_code - 1);
    //ui->buttonModeCode->setEnabled(true);

    ui->textEdit->setStyleSheet("background-color:white;");
    ui->textEdit->setFontItalic(false);
    ui->textEdit->setText(ui->textEdit->toPlainText() +
                          "\n________[END Code "+tr(out.str().c_str())+"]_______\n");*/
}


void MainWindow::createActions()
{
    // *********************** file action *********************************
    ui->actionNouvelle_Note = new QAction(QIcon(":/img/new.png"), tr("&New"), this);
    ui->actionNouvelle_Note->setShortcuts(QKeySequence::New);
    ui->actionNouvelle_Note->setStatusTip(tr("Créer un nouvel fichier"));
    connect(ui->actionNouvelle_Note, SIGNAL(triggered()), this, SLOT(openNote()));

    ui->actionOuvrir_une_note = new QAction(QIcon(":/img/open.png"), tr("&Open..."), this);
    ui->actionOuvrir_une_note->setShortcuts(QKeySequence::Open);
    ui->actionOuvrir_une_note->setStatusTip(tr("Ouvrir un fichier"));
    connect(ui->actionOuvrir_une_note, SIGNAL(triggered()), this, SLOT(openNote()));

    ui->actionSauvegarder = new QAction(QIcon(":/img/save.png"), tr("&Save"), this);
    ui->actionSauvegarder->setShortcuts(QKeySequence::Save);
    ui->actionSauvegarder->setStatusTip(tr("Sauvegarder"));

    // *********************** edit action *********************************
    ui->actionCouper = new QAction(QIcon(":/img/cut.png"), tr("Cu&t"), this);
    ui->actionCouper->setShortcuts(QKeySequence::Cut);
    ui->actionCouper->setStatusTip(tr("Couper"));
    connect(ui->actionCouper, SIGNAL(triggered()), ui->textEdit, SLOT(cut()));

    ui->actionCopier = new QAction(QIcon(":/img/copy.png"), tr("&Copy"), this);
    ui->actionCopier->setShortcuts(QKeySequence::Copy);
    ui->actionCopier->setStatusTip(tr("Coppier"));
    connect(ui->actionCopier, SIGNAL(triggered()), ui->textEdit, SLOT(copy()));

    ui->actionColler = new QAction(QIcon(":/img/paste.png"), tr("&Paste"), this);
    ui->actionColler->setShortcuts(QKeySequence::Paste);
    ui->actionColler->setStatusTip(tr("Coulier"));
    connect(ui->actionColler, SIGNAL(triggered()), ui->textEdit, SLOT(paste()));

    // *********************** help action *********************************
    //    ui->actionAbout = new QAction(tr("&About"), this);
    //    ui->actionAbout->setStatusTip(tr("Show the application's About box"));
    //    connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));

}

void MainWindow::createToolbars()
{
    // file action
    ui->mainToolBar->addAction(ui->actionNouvelle_Note);
    ui->mainToolBar->addAction(ui->actionOuvrir_une_note);
    //ui->mainToolBar->addAction(ui->actionSauvegarder);

    // separator
    ui->mainToolBar->addSeparator();

    // edit action
    ui->mainToolBar->addAction(ui->actionCouper);
    ui->mainToolBar->addAction(ui->actionCopier);
    ui->mainToolBar->addAction(ui->actionColler);

    ui->mainToolBar->addSeparator();

    // abbrevation tool
    //    ui->mainToolBar->addWidget(ui->newAbbreviation);
    //    ui->mainToolBar->addWidget(ui->label);
    //    ui->mainToolBar->addWidget(ui->valueAbbreviation);
    //    ui->mainToolBar->addWidget(ui->pushButton_addAbbr);
}

void MainWindow::on_buttonSaveAs_clicked()
{
    QString contenuText = ui->textEdit->toPlainText();

    QString newFile = QFileDialog::getSaveFileName(this, tr("Sauvegarder sous..."),
                                                   this->filename,
                                                   tr(" Nouvelle note(*.txt)"));

    FILE * file = fopen(newFile.toStdString().c_str(),"w");
    fprintf(file, contenuText.toStdString().c_str());
    fprintf(file, "\n");
    fclose(file);
    ui->mainToolBar->addSeparator();

    ui->mainToolBar->addWidget(ui->newAbbreviation);
    //    ui->mainToolBar->addWidget(ui->label);
    ui->mainToolBar->addWidget(ui->valueAbbreviation);
    ui->mainToolBar->addWidget(ui->pushButton_addAbbr);

}

void MainWindow::print()
{
    QPrinter *printer = new QPrinter();
    QPrintDialog *printerDialog = new QPrintDialog(printer);
    QPainter *painter = new QPainter();

    if (printerDialog->exec() == QDialog::Accepted)
    {
        painter->begin(printer);
        painter->drawText(50,20,ui->textEdit->toPlainText());
        painter->end();
    }
}
void MainWindow::insertImage()
{
    // convert input file name to char* type
    QString inputFilename = QFileDialog::getOpenFileName(this);
    int size = inputFilename.toStdString().size();
    char * src = new char[size + 1];
    src[size] = 0;
    strcpy(src,inputFilename.toStdString().c_str());

    // create picture name = currentFilename + pictureExtension
    // i, get fileName
    string currentPath = this->filename.toStdString();
    vector<string> split_string = file_util::split(currentPath,'/');
    string fileFullName = split_string.at(split_string.size() - 1);
    string fileName = file_util::split(fileFullName,'.').at(0);
    if (fileName.empty())
        return;

    // ii, get picture extension
    split_string = file_util::split(inputFilename.toStdString(),'/');
    fileFullName = split_string.at(split_string.size() - 1);
    string extension = file_util::split(fileFullName,'.').at(1);
    if (extension.empty())
        return;

    // iii, construct full path
    static int id = 0;
    QString fullPath =    tr(".images/")
            + fileName.c_str()
            + tr("_")
            + QString::number(id)
            + tr(".")
            + extension.c_str();
    id ++;

    // convert destination to char* format
    size = fullPath.size();
    char * des = new char[size + 1];
    des[size] = 0;
    strcpy(des,fullPath.toStdString().c_str());

    // copy to be inserted image to our db
    file_util::copyFile(src,des);
    if (!inputFilename.isEmpty())
    {
        QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml("<img src='" + fullPath + "'>");
        int currentPos = ui->textEdit->textCursor().position();
        ui->textEdit->textCursor().insertFragment(fragment);
        QHash<QString, int>::iterator i;
        // update position, if a image is inserted to text, then all the position of
        // the folowing images must add 1
        for (i = imagePositionList.begin(); i != imagePositionList.end(); ++i)
            if (i.value() > currentPos)
                i.value() = i.value() + 1;

        imagePositionList.insert("<img src='" + fullPath + "'>",currentPos);
    }

}
void MainWindow::on_buttonSave_clicked()
{
    // save file content
    QString contenuText = ui->textEdit->toPlainText();
    string fileName = this->filename.toStdString();
    FILE * file = fopen(fileName.c_str(),"w");
    fprintf(file, contenuText.toStdString().c_str());
    fclose(file);

    // save file metadata
    QTextCursor myCursor = ui->textEdit->textCursor();
    // Ordering image hyperlink after its position
    QMap<int, QString> orderedImageList;
    QHash<QString, int>::iterator i;
    for (i = imagePositionList.begin(); i != imagePositionList.end(); ++i)
        orderedImageList.insert(i.value(),i.key());

    // create line to persist
    QString picPosition;
    QMap<int, QString>::iterator j;
    for (j = orderedImageList.begin(); j != orderedImageList.end(); j++)
        picPosition = picPosition + QString::number(j.key()) + "*" + j.value() + "\n";
    ui->textEdit->setTextCursor(myCursor);

    // persist image
    string metadataFullName = file_util::split(fileName,'/').back();
    string metadataName = file_util::split(metadataFullName,'.').at(0);
    metadataName = ".data/img_" + metadataFullName;
    file = fopen(metadataName.c_str(),"w");
    fprintf(file, picPosition.toStdString().c_str());
    fclose(file);

    // save abbreviation
    QString abbr ;
    QHash<QString, QString>::iterator k;
    // separator is space
    for (k = abbreviationList.begin(); k != abbreviationList.end(); k++)
        abbr = abbr + k.key() + " " + k.value() + "\n";

    // pesist abbreviation
    metadataName = file_util::split(metadataFullName,'.').at(0);
    metadataName = ".data/abb_" + metadataFullName;
    file = fopen(metadataName.c_str(),"w");
    fprintf(file, abbr.toStdString().c_str());
    fclose(file);
}
